import UIKit
import Down

// 容器策略协议
public protocol MarkdownContainerStrategy {
    func createContainer() -> UIView
    func configureContainer(_ container: UIView)
    func renderMarkdown(_ markdown: String, theme: MarkdownTheme, imageBaseURL: URL?) -> NSAttributedString
}

// TextView 容器策略
public class TextViewContainerStrategy: MarkdownContainerStrategy {
    public init() {}
    
    public func createContainer() -> UIView {
        let textView = UITextView()
        textView.backgroundColor = .clear
        textView.isEditable = false
        textView.isScrollEnabled = true
        textView.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
        textView.textContainer.lineFragmentPadding = 0
        return textView
    }
    
    public func configureContainer(_ container: UIView) {
        guard let textView = container as? UITextView else { return }
        textView.isEditable = false
        textView.isScrollEnabled = true
        textView.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
        textView.textContainer.lineFragmentPadding = 0
    }
    
    public func renderMarkdown(_ markdown: String, theme: MarkdownTheme, imageBaseURL: URL?) -> NSAttributedString {
        let attributedString = NSMutableAttributedString()
        
        do {
            let down = Down(markdownString: markdown)
            let ast = try down.toAST()
            processNode(ast.wrap() as! Document, attributedString: attributedString, theme: theme, imageBaseURL: imageBaseURL)
        } catch {
            print("Error parsing markdown: \(error)")
        }
        
        return attributedString
    }
    
    private func processNode(_ node: Node, attributedString: NSMutableAttributedString, theme: MarkdownTheme, imageBaseURL: URL?) {
        switch node {
        case let heading as Heading:
            appendHeading(heading, attributedString: attributedString, theme: theme)
            
        case let paragraph as Paragraph:
            appendParagraph(paragraph, attributedString: attributedString, theme: theme)
            
        case let codeBlock as CodeBlock:
            appendCodeBlock(codeBlock, attributedString: attributedString, theme: theme)
            
        case let list as List:
            appendList(list, attributedString: attributedString, theme: theme)
            
        case let image as Image:
            appendImage(image, attributedString: attributedString, theme: theme, imageBaseURL: imageBaseURL)
            
        case let link as Link:
            appendLink(link, attributedString: attributedString, theme: theme)
            
        case let text as Text:
            appendText(text, attributedString: attributedString, theme: theme)
            
        case let emphasis as Emphasis:
            appendEmphasis(emphasis, attributedString: attributedString, theme: theme)
            
        case let strong as Strong:
            appendStrong(strong, attributedString: attributedString, theme: theme)
            
        case let blockQuote as BlockQuote:
            appendBlockQuote(blockQuote, attributedString: attributedString, theme: theme)
            
        default:
            // 处理其他节点类型
            for child in node.children {
                processNode(child, attributedString: attributedString, theme: theme, imageBaseURL: imageBaseURL)
            }
        }
    }
    
    private func appendHeading(_ heading: Heading, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let fontSize: CGFloat
        switch heading.headingLevel {
        case 1: fontSize = 28
        case 2: fontSize = 24
        case 3: fontSize = 20
        case 4: fontSize = 18
        case 5: fontSize = 16
        case 6: fontSize = 14
        default: fontSize = 16
        }
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.paragraphSpacing = 16
        paragraphStyle.paragraphSpacingBefore = 16
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: fontSize, weight: .bold),
            .foregroundColor: theme.heading.h1.textColor,
            .paragraphStyle: paragraphStyle
        ]
        
        let content = NSMutableAttributedString()
        for child in heading.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        content.addAttributes(attributes, range: NSRange(location: 0, length: content.length))
        
        attributedString.append(content)
        attributedString.append(NSAttributedString(string: "\n"))
    }
    
    private func appendParagraph(_ paragraph: Paragraph, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 6
        paragraphStyle.paragraphSpacing = 12
        
        let content = NSMutableAttributedString()
        for child in paragraph.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        
        content.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: content.length))
        attributedString.append(content)
        attributedString.append(NSAttributedString(string: "\n"))
    }
    
    private func appendCodeBlock(_ codeBlock: CodeBlock, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let containerStyle = NSMutableParagraphStyle()
        containerStyle.firstLineHeadIndent = 16
        containerStyle.headIndent = 16
        containerStyle.tailIndent = -16
        containerStyle.paragraphSpacing = 16
        containerStyle.paragraphSpacingBefore = 16
        
        // 代码块背景
        let backgroundAttributes: [NSAttributedString.Key: Any] = [
            .backgroundColor: theme.code.backgroundColor,
            .paragraphStyle: containerStyle
        ]
        attributedString.append(NSAttributedString(string: "\n", attributes: backgroundAttributes))
        
        // 语言标签
        if let language = codeBlock.fenceInfo {
            let headerStyle = NSMutableParagraphStyle()
            headerStyle.firstLineHeadIndent = 16
            headerStyle.headIndent = 16
            headerStyle.paragraphSpacing = 8
            
            let headerAttributes: [NSAttributedString.Key: Any] = [
                .font: UIFont.systemFont(ofSize: 12, weight: .medium),
                .foregroundColor: UIColor.secondaryLabel,
                .backgroundColor: theme.code.backgroundColor.withAlphaComponent(0.8),
                .paragraphStyle: headerStyle
            ]
            attributedString.append(NSAttributedString(string: language.uppercased() + "\n", attributes: headerAttributes))
        }
        
        // 代码内容
        let codeAttributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.monospacedSystemFont(ofSize: 14, weight: .regular),
            .foregroundColor: theme.code.textColor,
            .backgroundColor: theme.code.backgroundColor,
            .paragraphStyle: containerStyle
        ]
        
        let code = codeBlock.literal ?? ""
        attributedString.append(NSAttributedString(string: code + "\n", attributes: codeAttributes))
        attributedString.append(NSAttributedString(string: "\n", attributes: backgroundAttributes))
    }
    
    private func appendList(_ list: List, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.paragraphSpacing = 8
        paragraphStyle.headIndent = 20
        paragraphStyle.firstLineHeadIndent = 20
        
        for (index, child) in list.children.enumerated() {
            let itemContent = NSMutableAttributedString()
            #warning("test")
            //let bullet = list.listType == .bullet ? "• " : "\(index + 1). "
            let bullet = "• "
            
            itemContent.append(NSAttributedString(string: bullet, attributes: [
                .font: UIFont.systemFont(ofSize: 16),
                .foregroundColor: theme.base.textColor
            ]))
            
            processNode(child, attributedString: itemContent, theme: theme, imageBaseURL: nil)
            itemContent.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: itemContent.length))
            
            attributedString.append(itemContent)
            attributedString.append(NSAttributedString(string: "\n"))
        }
    }
    
    private func appendImage(_ image: Image, attributedString: NSMutableAttributedString, theme: MarkdownTheme, imageBaseURL: URL?) {
        if let urlString = image.url, let url = URL(string: urlString, relativeTo: imageBaseURL) {
            // 异步加载图片
            DispatchQueue.global().async {
                if let data = try? Data(contentsOf: url), let uiImage = UIImage(data: data) {
                    DispatchQueue.main.async {
                        let maxWidth = UIScreen.main.bounds.width - 64
                        let aspectRatio = uiImage.size.width / uiImage.size.height
                        let targetHeight = maxWidth / aspectRatio
                        
                        let attachment = NSTextAttachment()
                        attachment.image = uiImage
                        attachment.bounds = CGRect(x: 0, y: 0, width: maxWidth, height: targetHeight)
                        
                        let imageString = NSAttributedString(attachment: attachment)
                        attributedString.append(imageString)
                        attributedString.append(NSAttributedString(string: "\n\n"))
                    }
                }
            }
        }
    }
    
    private func appendLink(_ link: Link, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let linkAttributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: theme.link.defaultColors.textColor,
            .underlineStyle: NSUnderlineStyle.single.rawValue,
            .link: link.url ?? ""
        ]
        
        let content = NSMutableAttributedString()
        for child in link.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        content.addAttributes(linkAttributes, range: NSRange(location: 0, length: content.length))
        
        attributedString.append(content)
    }
    
    private func appendText(_ text: Text, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 16),
            .foregroundColor: theme.base.textColor
        ]
        attributedString.append(NSAttributedString(string: text.literal ?? "", attributes: attributes))
    }
    
    private func appendEmphasis(_ emphasis: Emphasis, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let content = NSMutableAttributedString()
        for child in emphasis.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        
        content.addAttribute(.font, value: UIFont.italicSystemFont(ofSize: 16), range: NSRange(location: 0, length: content.length))
        attributedString.append(content)
    }
    
    private func appendStrong(_ strong: Strong, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let content = NSMutableAttributedString()
        for child in strong.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        
        content.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 16), range: NSRange(location: 0, length: content.length))
        attributedString.append(content)
    }
    
    private func appendBlockQuote(_ blockQuote: BlockQuote, attributedString: NSMutableAttributedString, theme: MarkdownTheme) {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.firstLineHeadIndent = 20
        paragraphStyle.headIndent = 20
        paragraphStyle.paragraphSpacing = 12
        paragraphStyle.paragraphSpacingBefore = 12
        
        let quoteAttributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 16),
            .foregroundColor: theme.quote.textColor,
            .backgroundColor: theme.quote.backgroundColor,
            .paragraphStyle: paragraphStyle
        ]
        
        let content = NSMutableAttributedString()
        for child in blockQuote.children {
            processNode(child, attributedString: content, theme: theme, imageBaseURL: nil)
        }
        
        content.addAttributes(quoteAttributes, range: NSRange(location: 0, length: content.length))
        attributedString.append(content)
        attributedString.append(NSAttributedString(string: "\n"))
    }
} 
